package org.truenewx.tnxjee.core.enums;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.util.Assert;
import org.truenewx.tnxjee.core.Strings;
import org.truenewx.tnxjee.core.spec.BooleanEnum;
import org.truenewx.tnxjee.core.spec.Mutability;

/**
 * 枚举类型
 *
 * @author jianglei
 */
public class EnumType extends EnumTypeIdentity {
    /**
     * 说明
     */
    private String caption;
    /**
     * 可改动性
     */
    private Mutability mutability;

    /**
     * 枚举项映射集
     */
    private final Map<String, EnumItem> items = new LinkedHashMap<>();

    public EnumType(String name, String subname, String caption, Mutability mutability) {
        setName(name);
        setSubname(subname);
        setCaption(caption);
        this.mutability = mutability;
    }

    public String getCaption() {
        return this.caption;
    }

    protected void setCaption(String caption) {
        this.caption = caption;
    }

    public Mutability getMutability() {
        return this.mutability;
    }

    public void addItem(EnumItem item) {
        String value = item.getValue();
        Assert.isNull(getItemByValue(value),
                () -> "Item with value '" + value + "' for type '" + getName() + "' already exists");
        this.items.put(item.getKey(), item);
    }

    public EnumItem getItem(String key, String... keys) {
        if (BooleanEnum.class.getName().equals(getName())) {
            key = key.toUpperCase();
        }
        EnumItem item = this.items.get(key);
        if (item != null && keys.length > 0) {
            String[] subkeys = new String[keys.length - 1];
            if (subkeys.length > 0) {
                System.arraycopy(keys, 1, subkeys, 0, subkeys.length);
                item = item.getChild(keys[0], subkeys);
            }
        }
        return item;
    }

    /**
     * 获取所有直接枚举项
     *
     * @return 所有直接枚举项
     */
    public Collection<EnumItem> getItems() {
        return this.items.values();
    }

    /**
     * 设置直接枚举项集
     *
     * @param items 直接枚举项集
     */
    public void setItems(Collection<EnumItem> items) {
        synchronized (this.items) {
            this.items.clear();
            for (EnumItem item : items) {
                addItem(item);
            }
        }
    }

    public EnumItem getItemByCaption(String caption) {
        for (EnumItem item : this.items.values()) {
            if (item.getCaption().equals(caption)) {
                return item;
            }
        }
        return null;
    }

    public EnumItem getItemByValue(String value) {
        for (EnumItem item : this.items.values()) {
            if (item.getValue().equals(value)) {
                return item;
            }
        }
        return null;
    }

    @JsonIgnore
    public String getIdentity() {
        return super.toString();
    }

    @Override
    public String toString() {
        return getIdentity() + Strings.LEFT_BRACKET + this.caption + Strings.RIGHT_BRACKET;
    }

    public EnumType cloneWithoutItems() {
        return new EnumType(getName(), getSubname(), getCaption(), getMutability());
    }

}
